/*
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package eu.fastl.dragster.log.config;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.util.ValidationEventCollector;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class XlsExportConfigReader {

    private static final Logger LOGGER = LoggerFactory.getLogger(XlsExportConfigReader.class);

    private static final String SCHEMA_FILE = "/eu/fastl/dragster/log/xls-export.xsd";

    public XlsExportConfig readConfigFromFile(String fileName) {
        LOGGER.info("Reading Config from file:" + fileName);
        File configFile = new File(fileName);
        ValidationEventCollector validationEventCollector = new ValidationEventCollector();
        try {
            JAXBContext context = JAXBContext.newInstance(XlsExportConfig.class);
            Schema configSchema = getConfigSchema();
            Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setSchema(configSchema);
            unmarshaller.setEventHandler(validationEventCollector);
            return (XlsExportConfig) unmarshaller.unmarshal(configFile);

        } catch (JAXBException e) {
            LOGGER.error("Could not parse config file:" + fileName);
            if (validationEventCollector.hasEvents()) {
                for (int i = 0; i < validationEventCollector.getEvents().length; i++) {
                    ValidationEvent event = validationEventCollector.getEvents()[i];
                    StringBuilder msg = new StringBuilder("XML Validation Error");
                    msg.append(" line: ");
                    msg.append(event.getLocator().getLineNumber());
                    msg.append(" column: ");
                    msg.append(event.getLocator().getColumnNumber());
                    msg.append(" message: ");
                    msg.append(event.getMessage());
                    LOGGER.error(msg.toString());
                }
            }
            throw new IllegalStateException(e);
        }
    }

    private Schema getConfigSchema() {
        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        InputStream inputStream = null;
        try {
            inputStream = XlsExportConfigReader.class.getResourceAsStream(SCHEMA_FILE);
            return sf.newSchema(new StreamSource(inputStream));
        } catch (Exception e) {
            throw new IllegalStateException("Could not read config schema: " + SCHEMA_FILE, e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    throw new IllegalStateException("Could not close Schema Stream", e);
                }
            }
        }
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}
